package com.bruce.spring.http.client.factory;

import com.bruce.spring.http.client.monitor.JdkHttpClientMonitor;
import lombok.RequiredArgsConstructor;
import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.springframework.http.client.reactive.HttpComponentsClientHttpConnector;
import org.springframework.http.client.reactive.JdkClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.support.WebClientAdapter;
import org.springframework.web.service.invoker.HttpExchangeAdapter;
import reactor.netty.http.HttpProtocol;
import reactor.netty.http.client.HttpClient;

import java.time.Duration;

/**
 * Created by bruce in 2025/6/29 02:08
 */
@RequiredArgsConstructor
@Component
public class WebClientAdapterCreator implements HttpExchangeAdapterCreator {

    private final JdkHttpClientMonitor jdkHttpClientMonitor;

    // Reactor netty http client
    public HttpExchangeAdapter useReactorNettyHttpClient(String url) {
        HttpClient httpClient = HttpClient.create().protocol(HttpProtocol.H2C, HttpProtocol.HTTP11);
        WebClient webClient = WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .baseUrl(url)
                .build();
        return WebClientAdapter.create(webClient);
    }

    // Jdk9+ httpClient
    public HttpExchangeAdapter useJdk9HttpClient(String url) {
        java.net.http.HttpClient httpClient = java.net.http.HttpClient.newBuilder()
                .connectTimeout(Duration.ofMillis(5000))
                .build();

        jdkHttpClientMonitor.registryHttpClient("default", httpClient);

        WebClient webClient = WebClient.builder()
                .clientConnector(new JdkClientHttpConnector(httpClient))
                .baseUrl(url)
                .build();
        return WebClientAdapter.create(webClient);
    }

    // Apache HttpClient5
    public HttpExchangeAdapter useApacheHttpClient5(String url) {
        PoolingAsyncClientConnectionManager clientConnectionManager = new PoolingAsyncClientConnectionManager();
        clientConnectionManager.setDefaultTlsConfig(
                TlsConfig.custom()
                        .setVersionPolicy(HttpVersionPolicy.NEGOTIATE)
                        .build()
        );
        MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(clientConnectionManager);

        WebClient webClient = WebClient.builder()
                .clientConnector(new HttpComponentsClientHttpConnector(client))
                .baseUrl(url)
                .build();
        return WebClientAdapter.create(webClient);
    }

    // Jdk HttpUrlConnection
    public HttpExchangeAdapter useHttpUrlConnection(String url) {
        throw new UnsupportedOperationException();
    }

}
